package projects

import (
	"encoding/json"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/validation"
	"log"
	"strconv"
	"strings"
	"xpms/app/auth/users"
	"xpms/controllers"
	"xpms/cores"
	"xpms/cores/utils"
	"xpms/cores/utils/stream"
)

//  任务管理
type TaskProjectController struct {
	controllers.BaseController
}

// @Title 分页查询任务数据
// @Description 分页查询任务数据
// @Param	id		path 	string	true		"项目id"
// @Param	planid		query 	[]string			"计划id"
// @Param	acceptid		query 	[]string			"负责人"
// @Param	moduleid		query 	[]string			"模块"
// @Param	status		query 	[]string			"状态"
// @Param	taskid		query 	string			"任务id"
// @Param	onetaskid		query 	string			"任务id"
// @Param	testid		query 	string			"反馈id"
// @Success 200 {object} projects.ProjectsAllTask   int   int  int
// @Failure 403 任务 not exist
// @router /:id/page [get]
func (u *TaskProjectController) Page() {
	id, err := u.GetInt64(":id")
	if err != nil || id < 0 {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "未知项目" + err.Error()}
		u.ServeJSON()
		return
	}
	planid := u.GetStrings("planid")
	onetaskid := u.GetStrings("onetaskid")
	//acceptid := u.GetStrings("acceptid")
	//moduleid := u.GetStrings("moduleid")
	//tasktid := u.GetStrings("tasktid")
	//testid := u.GetStrings("testid")
	condArr := make(map[string]interface{})
	condArr["projectid"] = id
	condArr["planid"] = planid
	condArr["taskid"] = onetaskid
	//condArr["acceptid"] = acceptid
	//condArr["moduleid"] = moduleid
	//condArr["planid"] = planid
	//condArr["taskid"] = taskid
	//condArr["testid"] = testid
	modeData := TaskPageExec(condArr)
	streamTask, _ := stream.New(modeData)
	taskIds := make([]int64, 0)
	streamTask.Map(func(s ProjectsAllTask) int64 {
		return s.Id
	}).ToSlice(&taskIds)
	relCondArr := make(map[string]interface{})
	relCondArr["taskid"] = taskIds
	TaskRelateds := TaskRelatedPageExec(relCondArr)
	TaskTimes := TaskTimeExec(relCondArr, 1, 100)
	streamFilter, _ := stream.New(TaskRelateds)
	TaskTimesFilter, _ := stream.New(TaskTimes)
	var upd []ProjectsAllTask
	for _, v := range modeData {
		streamFilter.Filter(func(s ProjectTaskRelatedVo) bool {
			return s.Taskid == v.Id
		}).ForEach(func(s ProjectTaskRelatedVo) {
			v.Related = append(v.Related, s)
		})
		TaskTimesFilter.Filter(func(s ProjectsTaskTimeAll) bool {
			return s.Taskid == v.Id
		}).ForEach(func(s ProjectsTaskTimeAll) {
			v.Tasktimes = append(v.Tasktimes, s)
		})
		upd = append(upd, v)
	}
	var responseEntity cores.ResponseEntity
	u.Data["json"] = responseEntity.Build(upd).Data
	u.Ctx.Output.Status = responseEntity.StatusCode
	u.ServeJSON()
}

type TaskDto struct {
	Needsid          int64 `json:"Needsid,string"`
	Needsname        string
	Projectid        int64 `json:"Projectid,string"`
	Projectname      string
	Testid           int64 `json:"Testid,string"` // 从反馈表中获取
	Userid           int64 `json:"Userid,string"`
	Userrealname     string
	Acceptid         int64 `json:"Acceptid,string"`
	Acceptrealname   string
	Ccid             string
	Completeid       int64 `json:"Completeid,string"`
	Completerealname string
	Name             string
	Desc             string
	Acceptance       string
	Type             int `json:"Type,string"`
	Level            int `json:"Level,string"`
	Tasktime         int `json:"Tasktime,string"`
	Started          int64
	Ended            int64
	Attachment       string
	Created          int64
	Changed          int64
	Status           int   `json:"Status,string"`
	Closeid          int64 `json:"Closeid,string"`
	Cancelid         int64 `json:"Cancelid,string"`
	Testname         string
	Moduleid         int64 `json:"Moduleid,string"`
	Modulename       string
	Actualstarttime  int64
	Actualendtime    int64
	Stage            int `json:"Stage,string"`
	Source           int
	Parenttaskid     int64 `json:"Parenttaskid,string"`
	Planid           int64 `json:"Planid,string"`
	Classify         int   `json:"Classify,string"`
	Progress         int   `json:"Progress,string"`
}

// 如果你的 struct 实现了接口 validation.ValidFormer
// 当 StructTag 中的测试都成功时，将会执行 Valid 函数进行自定义验证
func (u *TaskDto) Valid(v *validation.Validation) {
	v.Required(u.Name, "Name").Message("标题不能为空")

}

// @Title Create task
// @Description create task
// @Param	body		body 	projects.TaskDto	true		"body for task content"
// @Success 200 {int} projects.ProjectsTask.Id
// @Failure 403 body is empty
// @router / [post]
func (u *TaskProjectController) Create() {
	var dto TaskDto
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	// 开始校验输入值
	valid := validation.Validation{}
	if utils.IsEmpty(dto.Classify) && dto.Classify == 2 {
		valid.Required(dto.Level, "Level").Message("级别不能为空")
		valid.Required(dto.Moduleid, "Moduleid").Message("模块不能为空")
	}
	b, err := valid.Valid(&dto)
	valid.Required(dto.Projectid, "Projectid").Message("项目id为空")
	if err != nil {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
		u.ServeJSON()
		return
	}
	if !b {
		var validMsg []string
		// validation does not pass
		for _, err := range valid.Errors {
			validMsg = append(validMsg, err.Message)
			log.Println(err.Key, err.Message)
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	task := new(ProjectsTask)
	utils.SimpleCopyProperties(task, dto)
	tid := utils.SnowFlakeId()
	task.Id = tid
	task.Userid = u.BaseController.UserUserId
	err = AddTask(u.UserUsername, *task)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "任务添加成功", "id": fmt.Sprintf("%d", tid)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "任务添加失败"}
	}
	u.ServeJSON()
}

// @Title Update Task
// @Description   Update Task
// @Param	id		path 	string	true		"Task id"
// @Param	body		body 	projects.TaskDto	true		"body for Task content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id [put]
func (u *TaskProjectController) Update() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的任务为空"}
		u.ServeJSON()
		return
	}
	var dto TaskDto
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	// 开始校验输入值
	//valid := validation.Validation{}
	//b, err := valid.Valid(&dto)
	//if err != nil {
	//	// handle error
	//	u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
	//	u.ServeJSON()
	//	return
	//}
	//if !b {
	//	var validMsg []string
	//	// validation does not pass
	//	for _, err := range valid.Errors {
	//		validMsg = append(validMsg, err.Message)
	//		log.Println(err.Key, err.Message)
	//	}
	//	if !utils.IsEmpty(validMsg) {
	//		u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
	//		u.ServeJSON()
	//		return
	//	}
	//}
	userss, err1 := GetProjectTask(ids)
	if err1 != nil || utils.IsEmpty(userss.Name) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "反馈不存在"}
		u.ServeJSON()
		return
	}
	task := new(ProjectsTask)
	utils.SimpleCopyProperties(task, dto)
	task.Id = ids
	//task.Userid = u.BaseController.UserUserId
	err = UpdateTask(ids, u.BaseController.UserUserId, u.UserUsername, *task)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败"}
	}
	u.ServeJSON()

}

// @Title Get
// @Description get task  by id
// @Param	id		path 	string	true		"The key for task"
// @Success 200 {object} projects.ProjectsTask
// @Failure 403 :id is empty
// @router /:id [get]
func (u *TaskProjectController) Get() {
	uid := u.GetString(":id")
	if uid != "" {
		var responseEntity cores.ResponseEntity
		int64, err := strconv.ParseInt(uid, 10, 64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
			return
		}
		dbData, err := GetProjectTask(int64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
		} else {
			u.Data["json"] = responseEntity.Build(dbData).Data
			u.Ctx.Output.Status = responseEntity.StatusCode
		}
	}
	u.ServeJSON()
}

// @Title Update task accept
// @Description  Update task accept
// @Param	id		path 	string	true		"task id"
// @Param	acceptid	query 	string	true		"指派人员"
// @Param	completeid	query 	string	true		"完成人"
// @Param	note	query 	string			"备注"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/accept [put]
func (u *TaskProjectController) UpdateAccept() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的反馈为空"}
		u.ServeJSON()
		return
	}
	acceptid, _ := u.GetInt64("acceptid")
	completeid, _ := u.GetInt64("completeid")
	//note := u.GetString("note")
	var task ProjectsTask
	task.Id = ids
	task.Acceptid = acceptid
	task.Completeid = completeid
	//task.Note = note
	err = ChangeProjectTaskAccept(ids, u.UserUsername, task)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败"}
	}
	u.ServeJSON()
}

// @Title Update task status
// @Description  Update test status
// @Param	id		path 	string	true		"task id"
// @Param	status	query	int		"状态"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/status [put]
func (u *TaskProjectController) UpdateStaus() {
	ids, err := u.GetInt64(":id")
	if ids <= 0 || err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请选择任务"}
		u.ServeJSON()
		return
	}
	var dto TaskDto
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	Status := dto.Status
	if Status <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请选择操作状态"}
		u.ServeJSON()
		return
	}
	err = ChangeProjectTaskStatus(ids, u.BaseController.UserUserId, u.UserUsername, Status)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "状态更改成功"}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "状态更改失败"}
	}
	u.ServeJSON()
}

type TaskRelatedDto struct {
	Id              int64 `json:"Id,string"`
	Type            int   `json:"Type,string"`
	Taskid          int64 `json:"Taskid,string"`
	Related         int64 `json:"Related,string"`
	Directionafter  int64 `json:"Directionafter,string"`
	Directionbefore int64 `json:"Directionbefore,string"`
	Started         int64
	Ended           int64
	Progress        int64
	Status          int `json:"Status,string"`
	Oper            int `json:"Oper,string"` //1 删除
}

// 如果你的 struct 实现了接口 validation.ValidFormer
// 当 StructTag 中的测试都成功时，将会执行 Valid 函数进行自定义验证
func (u *TaskRelatedDto) Valid(v *validation.Validation) {
	v.Required(u.Taskid, "Taskid").Message("任务id不能为空")
	v.Required(u.Related, "Related").Message("关联任务id不能为空")
}

// @Title Update Task  Related
// @Description   Update Task Related
// @Param	body		body 	[]projects.TaskRelatedDto	true		"body for Task content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /related [post]
func (u *TaskProjectController) CreateRelated() {
	var dto []TaskRelatedDto
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	// 开始校验输入值
	valid := validation.Validation{}
	var validMsg []string
	for _, v := range dto {
		b, err := valid.Valid(&v)
		if err != nil {
			// handle error
			u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
			u.ServeJSON()
			return
		}
		if !b {
			// validation does not pass
			for _, err := range valid.Errors {
				validMsg = append(validMsg, err.Message)
				log.Println(err.Key, err.Message)
			}
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	err = AddRelated(u.UserUserId, u.UserUsername, dto)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功"}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败" + err.Error()}
	}
	u.ServeJSON()

}

type TaskCommentDto struct {
	Id         int64 `json:"Taskid,string"`
	Note       string
	Attachment string
}

// @Title 创建评论
// @Description   创建评论
// @Param	body		body 	projects.TaskCommentDto	true		"body for Task  comment content"
// @Success 200 {string} 创建评论成功
// @Failure 403 body is empty
// @router /comment [post]
func (u *TaskProjectController) CreateComment() {
	var dto TaskCommentDto
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	if err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "解析json错误" + err.Error()}
		u.ServeJSON()
		return
	}
	// 开始校验输入值
	valid := validation.Validation{}
	var validMsg []string
	for _, err := range valid.Errors {
		validMsg = append(validMsg, err.Message)
		log.Println(err.Key, err.Message)
	}
	if !utils.IsEmpty(validMsg) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
		u.ServeJSON()
		return
	}
	if dto.Note != "<p><br></p>" {
		var comment ProjectsTaskComments
		id := utils.SnowFlakeId()
		comment.Id = id
		comment.Taskid = dto.Id
		userid := u.BaseController.UserUserId
		comment.UserName = u.BaseController.UserUsername
		comment.Userid = userid
		comment.Comment = dto.Note
		comment.Attachment = dto.Attachment
		err := AddTaskComments(comment)
		if err == nil {
			u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功"}
		} else {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败" + err.Error()}
		}
		u.ServeJSON()
	}
}

// @Title 分页查询评论数据
// @Description 分页查询评论数据
// @Param	id		path 	string	true		"任务id"
// @Success 200 {object} projects.ProjectsTaskComments   int   int  int
// @Failure 403 评论 not exist
// @router /:id/comment/list [get]
func (u *TaskProjectController) CommentList() {
	id, err := u.GetInt64(":id")
	if err != nil || id < 0 {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "未知任务"}
		u.ServeJSON()
		return
	}
	u.Data["json"] = ListProjectTaskComment(id)
	u.ServeJSON()
}

type TaskOrderDto struct {
	Ptaskid   int64 `json:"Ptaskid,string"`
	Neworders int   //新顺序号
	Oldorders int   //以前的顺序号
}

// 如果你的 struct 实现了接口 validation.ValidFormer
// 当 StructTag 中的测试都成功时，将会执行 Valid 函数进行自定义验证
func (u *TaskOrderDto) Valid(v *validation.Validation) {
	v.Required(u.Ptaskid, "Ptaskid").Message("父任务id不存在")
	v.Required(u.Neworders, "Neworders").Message("请输入新顺序")
	v.Required(u.Oldorders, "Oldorders").Message("请输入旧顺序")
}

// @Title Update task order
// @Description  Update task order
// @Param	id		path 	string	true		"task id"
// @Param	body		body 	projects.TaskOrderDto	true		"body for Task  排序 content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/order [put]
func (u *TaskProjectController) UpdateOrder() {
	ids, err := u.GetInt64(":id")
	if ids <= 0 || err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请选择任务"}
		u.ServeJSON()
		return
	}
	var dto TaskOrderDto
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &dto)
	//如果以前的顺序心大于现在的顺序就下移 否则就上移
	//先拿到拖拽之前的数据的排序
	//根据新下标和老下标拿到新的权重（就是排序字段，下面统称权重）和老的权重
	//如果以前的权重>现在的权重，就是往下移动（为什么做这个判断，因为上移除了拖拽的数据，其他的权重是-1，否则相反）
	//如果是下移，先设置修改的区间，
	//开始区间为now.Neworders，结束区间为ago.Oldorders-1，因为不包含拖拽的那条数据，那条数据单独修改
	//然后调用upTask，给他们通通+1，然后再单独修改被拖拽的那条数据
	//上移的话，就结束区间+1，因为不包含拖拽的那条数据
	//然后将区间内的数据的权重通通-1，再单独修改拖拽的那条数据
	o := orm.NewOrm()
	to, err := o.Begin()
	if dto.Oldorders > dto.Neworders {
		dto.Oldorders = dto.Oldorders - 1
		err = upTask(to, ids, dto)
		if err != nil {
			goto breakHere
		}
	} else {
		dto.Oldorders = dto.Oldorders + 1
		err = downTask(to, ids, dto)
		if err != nil {
			goto breakHere
		}
	}
	err = updateTask(to, ids, dto)
	if err != nil {
		goto breakHere
	}
	to.Commit()
breakHere:
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "顺序调整成功"}
	} else {
		to.Rollback()
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "顺序调整失败" + err.Error()}
	}
	u.ServeJSON()
}

type TaskResourceDTO struct {
	Id      int64 `json:"Id,string"`
	Name    string
	AllTask []TaskResource
}

// @Title 查询岗位下的人员工作时间
// @Description 查询岗位下的人员工作时间
// @Param	id		path 	string	true		"项目id"
//@Param	planid		query 	[]string			"计划id"
// @Success 200 {object} projects.TaskResourceDTO   int   int  int
// @Failure 403 任务 not exist
// @router /:id/resource/list [get]
func (u *TaskProjectController) ResourceList() {
	id, err := u.GetInt64(":id")
	if err != nil || id < 0 {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "未知项目" + err.Error()}
		u.ServeJSON()
		return
	}
	planid := u.GetStrings("planid")
	condArr := make(map[string]interface{})
	condArr["projectid"] = id
	condArr["planid"] = planid
	condPositions := make(map[string]string)
	condPositions["status"] = "1"
	_, err, deps := users.ListPositions(condPositions)
	ops := TaskReourceExec(condArr)
	stream, _ := stream.New(ops)
	var TaskResources []TaskResourceDTO
	for _, v := range deps {
		var resource TaskResourceDTO
		resource.Id = v.Id
		resource.Name = v.Name
		tasks := new([]TaskResource)
		stream.Filter(func(s TaskResource) bool {
			return s.Positionid == v.Id
		}).ToSlice(tasks)
		resource.AllTask = *tasks
		TaskResources = append(TaskResources, resource)
	}
	u.Data["json"] = TaskResources
	u.ServeJSON()
}
